<?php

namespace Parse;

class MathParser
{
    public static function parse($string)
    {
        $math_parser = new RecursiveParser(
            "math_exp",
            array(
            "math_exp" => new CondParser(
                array(
                  "op_exp",
                  "paren_exp",
                  "number",
                  )
            ),
            "number" => new  CombinatorParser(
                array("whitespace",
                  new RegexParser(
                      "#^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][-+]?[0-9]+)?#"
                  ),
                  "whitespace"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "op_exp" => new CombinatorParser(
                array("num_or_paren_exp",
                  "tail_exp",
                  "tail_exps"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "num_or_paren_exp" => new CondParser(
                array("paren_exp", "number")
            ),
            "paren_exp" => new CombinatorParser(
                array("open_paren",
                  "math_exp",
                  "close_paren"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "tail_exp" => new CombinatorParser(
                array("op", "num_or_paren_exp"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "tail_exps" => new MultiParser(
                "tail_exp",
                function () {
                    return implode("", func_get_args());
                }
            ),
            "op" => new CondParser(
                array(new StringParser("+"),
                  new StringParser("-"),
                  new StringParser("*"),
                  new StringParser("/")),
                function ($op) {
                    return " " . $op . " ";
                }
            ),
            "open_paren" => new CombinatorParser(
                array("whitespace",
                          new StringParser("("),
                  "whitespace"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "close_paren" => new CombinatorParser(
                array("whitespace",
                          new StringParser(")"),
                  "whitespace"),
                function () {
                    return implode("", func_get_args());
                }
            ),
            "whitespace" => new RegexParser("#^[ ]*#")
            )
        );
        return $math_parser->parse($string);
    }
}
